<html>
<head>
<title>POJava HOWTO: DateTime</title>
<LINK REL="stylesheet" HREF="/style/pojava.css" TYPE="text/css"
	MEDIA=screen />
</head>
<body>
<h1>HOWTO use POJava DateTime</h1>
<p>DateTime is a class used for parsing, storing, and manipulating
Date and Time. It provides a number of advances over Java's Date object,
including immutability, nanosecond precision, and calculation functions
such as "add" and "truncate". It can parse dates and times without
requiring a specific format, and has integrated formatting into its
toString() output to make custom formatting simple and elegant.
</p>
<p>DateTime has excellent support for business use cases involving
multiple time zones, languages, locales and formats.  Default behaviors can be
customized either globally, for a set of dates sharing a common isolated
configuration, or catered to individual DateTime instances.</p>

<h3>Parsing Flexibility</h3>
<p>DateTime will correctly parse precise date and time from the following
strings without specifying any formats.  
</p>
<ul>
<li>1/26/69</li>
<li>January 26, 1969 at 3:21 PM</li>
<li>26-jan-1969 at 3:21:00.123 pm</li>
<li>1969-01-26 15:21:00.123456 PM PST</li>
<li>This 4th day of July, 1776</li>
<li>le 26.1.1969</li>
<li>el 29 de febrero de 2000</li>
<li>il 12 luglio del 2013</li>
</ul>

<h3>It supports both MDY and DMY ordering of month and day</h3>
<p>A date specified as, say, "11/10/2014" is ambiguous from an international perspective.  In some locales, such as
the United States or the Phillipines, that date would be interpreted as "2014-11-10" (November 10, 2014).  In the vast majority
of the world, such as Europe or Brazil, that same date string is interpreted as "2014-10-11" (October 11, 2014).  The DateTime
object always uses an IDateTimeConfig to resolve such differences, either from the default specified in the DateTimeConfig singleton,
or from a custom IDateTimeConfig passed to the constructor as a parameter to determine which interpretation to use.</p>
<p>Let's look at the default behavior.  When a DateTime is constructed with no IDateTimeConfig parameter, it looks to
DateTimeConfig.getGlobalDefault() to provide a default.  If it's defined, it will use it.  If not, it will construct and and retain
a static instance of DateTimeConfig, which it will initialize based on the system's TimeZone and Locale registered in Java.
Specifically, both the parser and formatter will be registered to use the system's default time zone, and the interpretation of
DMY vs MDY order will be determined by the system's Locale.  A desktop app or a local server using DateTime will typically
need no special configuration and things will just work as one would expect.</p>
<pre>
DateTime dt1=new DateTime("01/02/2003");
// This would, by default, be interpreted by a server in France as 2003-02-01, and as 2003-01-02 on a server in the U.S.
</pre>
<p>Now, let's say you're hosting a server near the Brazillian west coast, and processing data from a customer in the U.S.
east coast which is outputting localized dates in Pacific Daylight Time.  You don't want your system
defaults to be configured that way, so one way to handle this is to build a custom DateTimeConfig and use that one
config to process all dates in the batch.</p>
<pre>
DateTimeConfigBuilder builder = DateTimeConfigBuilder.newInstance();
builder.setDmyOrder(false);
builder.setInputTimeZone(TimeZone.getTimeZone("America/Los_Angeles")); // Used by parser
builder.setOutputTimeZone(TimeZone.getTimeZone("America/Porto_Velho")); // Used by formatter
IDateTimeConfig config=DateTimeConfig.fromBuilder(builder);
DateTime dt1=new DateTime("01/02/2003 13:30", config);
// This would be interpreted as 2003-01-02 13:30:00 PDT, which is 3 hours behind.
// The toString() output would be "2013-01-02 16:30:00", based on the output time zone.
</pre>

<h2>How do I work with this DateTime class?</h2>
<p>Working with DateTime is both easy and powerful. It's designed so
that simple tasks are simple and difficult tasks are possible. While
mostly intuitive, it helps to understand a few basic concepts.</p>
<ol class="defs">
	<li><em>Internal Representation</em>
	<p>A DateTime represents an instant in time in UTC (Universal Time,
	Coordinated), informally GMT or Zulu time. You can select the time
	zone, format, and locale (language) of displayed or printed output.</p>
	<li><em>Relationship with DateTimeConfig</em>
	<p>Every DateTime value is associated with an implementation of IDateTimeConfig.
	That object holds several variables affecting how DateTime will perform
	during input, processing, and output of values. When unspecified, the
	static DateTimeConfig.globalDefault is used. You can specify a time
	zone or locale in the constructor to override the default. In that
	case, a wrapper class called LocalConfig is used as a proxy which overrides
    a few of the variables and serves the others as a pass-through.</p>
	</li>
	<li><em>Input Rules</em>
	<p>The config.inputTimeZone determines the default time zone
	assumed for an input string when no time zone is specified in the
	string itself. The DateTime object will use that time zone to calculate
	the internal UTC representation of that instant in time, as well as any
    other input calculations. All formatted outputs are based on config.outputTimeZone.<br></br>
	</p>
	<p>DMY vs MDY formatting of dates can be a source of
	ambiguity, as one may interpret the date 01/02/2003 as February 1, and
	the other as January 2. You can choose whether the parser interprets
	such dates in Day/Month/Year order or Month/Day/Year order by setting
	the value dmyOrder to true or false. Two digit years are also
	ambiguous. By default, POJava treats such dates as 80 years in the past
	and 20 years into the future. When a date to parse is known to always
	be in the past, such as a date of birth, you can set the value
	config.unspecifiedCenturyAlwaysInPast to true to map 2-digit years to
	the past 100 years.</p>
	</li>
	<li><em>Processing Rules</em>
	<p>The config.outputTimeZone is used for DateTime calculations. For
	example, if a date was parsed from a string specifying "GMT" as the
	time zone, and the config.OutputTimeZone was set to the "PST" time
	zone, then the DateTime's truncate(CalendarUnit.Day) would round down
	to midnight as of the PST time zone. The original config is transferred
	to the newly calculated DateTime.</p>
	</li>
	<li><em>Output Rules</em>
	<p>The config.outputTimeZone, config.locale, and config.format
	values determine the appearance of the toString() output.
	OutputTimeZone affects what date and hour is displayed for that instant
	in time. The locale affects the presentation of word values such as
	month names or days of the week.</p>
	</li>
</ol>
<h2>Some Examples of DateTime in Use</h2>
<h3>Basic Parsing in Default Time Zone</h3>
<pre>
String date="26-Feb-2020 9:43:17 pm";
DateTime dt=new DateTime(date);
System.out.println(dt.toString());
</pre>

<h3>Conversion of UTC to Eastern Standard Time</h3>
One method is by overriding the toString() format.
<pre>
String utc="2011/12/13T14:15:16Z";
DateTime dt=new DateTime(utc);
System.out.println(dt.toString("yyyy-MM-dd HH:mm:ss z", TimeZone.getTimeZone("EST"));
</pre>
Another method is to declare both input and output timezones in the constructor.
<pre>
String utc="2011/12/13T14:15:16Z";
TimeZone tzUTC=TimeZone.getTimeZone("UTC");
TimeZone tzEST=TimeZone.getTimeZone("EST");
System.out.println(new DateTime(utc, tzUTC, tzEST).toString());
</pre>

</body>
</html>
